import { ApiProperty } from '@nestjs/swagger'
import { Type, Expose } from 'class-transformer'
import { IsOptional, IsInt, Min, Max, IsString, IsEnum, ValidateNested } from 'class-validator'

/**
 * 基础DTO类
 */
export class BaseDto {
  @ApiProperty({ description: 'ID' })
  @Expose()
  id: string

  @ApiProperty({ description: '创建时间' })
  @Expose()
  createdAt: Date

  @ApiProperty({ description: '更新时间' })
  @Expose()
  updatedAt: Date
}

/**
 * 排序方向枚举
 */
export enum SortOrder {
  ASC = 'asc',
  DESC = 'desc'
}

/**
 * 分页查询DTO基类
 */
export class PaginationDto {
  @ApiProperty({
    description: '页码',
    minimum: 1,
    default: 1,
    required: false
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt({ message: '页码必须是整数' })
  @Min(1, { message: '页码不能小于1' })
  page?: number = 1

  @ApiProperty({
    description: '每页数量',
    minimum: 1,
    maximum: 100,
    default: 10,
    required: false
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt({ message: '每页数量必须是整数' })
  @Min(1, { message: '每页数量不能小于1' })
  @Max(100, { message: '每页数量不能超过100' })
  limit?: number = 10

  @ApiProperty({
    description: '排序字段',
    required: false
  })
  @IsOptional()
  @IsString({ message: '排序字段必须是字符串' })
  sortBy?: string

  @ApiProperty({
    description: '排序方向',
    enum: SortOrder,
    default: SortOrder.DESC,
    required: false
  })
  @IsOptional()
  @IsEnum(SortOrder, { message: '排序方向必须是asc或desc' })
  sortOrder?: SortOrder = SortOrder.DESC

  @ApiProperty({
    description: '搜索关键词',
    required: false
  })
  @IsOptional()
  @IsString({ message: '搜索关键词必须是字符串' })
  search?: string
}

/**
 * 分页响应DTO基类
 */
export class PaginationResponseDto<T> {
  @ApiProperty({ description: '数据列表' })
  data: T[]

  @ApiProperty({ description: '总数量' })
  total: number

  @ApiProperty({ description: '当前页码' })
  page: number

  @ApiProperty({ description: '每页数量' })
  limit: number

  @ApiProperty({ description: '总页数' })
  totalPages: number

  @ApiProperty({ description: '是否有下一页' })
  hasNext: boolean

  @ApiProperty({ description: '是否有上一页' })
  hasPrev: boolean

  constructor(data: T[], total: number, page: number, limit: number) {
    this.data = data
    this.total = total
    this.page = page
    this.limit = limit
    this.totalPages = Math.ceil(total / limit)
    this.hasNext = page < this.totalPages
    this.hasPrev = page > 1
  }
}

/**
 * 通用响应DTO
 */
export class ResponseDto<T = any> {
  @ApiProperty({ description: '状态码' })
  code: number

  @ApiProperty({ description: '响应消息' })
  message: string

  @ApiProperty({ description: '响应数据' })
  data?: T

  @ApiProperty({ description: '时间戳' })
  timestamp?: string

  @ApiProperty({ description: '请求路径' })
  path?: string

  constructor(code: number, message: string, data?: T, path?: string) {
    this.code = code
    this.message = message
    this.data = data
    this.timestamp = new Date().toISOString()
    this.path = path
  }

  static success<T>(data?: T, message: string = '操作成功'): ResponseDto<T> {
    return new ResponseDto(200, message, data)
  }

  static error(code: number = 500, message: string = '操作失败'): ResponseDto {
    return new ResponseDto(code, message)
  }
}

/**
 * ID参数DTO
 */
export class IdParamDto {
  @ApiProperty({
    description: 'ID',
    example: '123e4567-e89b-12d3-a456-426614174000'
  })
  @IsString({ message: 'ID必须是字符串' })
  id: string
}

/**
 * 批量操作DTO
 */
export class BulkOperationDto {
  @ApiProperty({
    description: 'ID列表',
    type: [String],
    example: ['123e4567-e89b-12d3-a456-426614174000']
  })
  @IsString({ each: true, message: '每个ID必须是字符串' })
  ids: string[]
}

/**
 * 状态更新DTO
 */
export class StatusUpdateDto {
  @ApiProperty({
    description: '状态',
    example: 'active'
  })
  @IsString({ message: '状态必须是字符串' })
  status: string
}
